package com.grace.web.controller.cms;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FilenameUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.oly.cms.admin.service.ICmsThemeService;
import com.oly.cms.admin.service.ICmsWebService;
import com.oly.cms.common.domain.entity.CmsTheme;
import com.oly.cms.common.domain.entity.CmsWeb;
import com.oly.cms.common.model.properties.OlyThemeConfigProperties;
import com.oly.cms.common.model.properties.OlyWebConfigProperties;
import com.grace.common.annotation.Log;
import com.grace.common.constant.HttpStatus;
import com.grace.common.core.controller.BaseController;
import com.grace.common.core.domain.AjaxResult;
import com.grace.common.core.page.TableDataInfo;
import com.grace.common.enums.BusinessType;
import com.grace.common.utils.StringUtils;
import com.grace.system.domain.SysConfig;
import com.grace.system.service.impl.SysConfigServiceImpl;

//统一主题管理入口
@RestController
@RequestMapping("/cms/theme")
public class CmsThemeController extends BaseController {

    @Autowired
    private ICmsThemeService cmsThemeService;

    @Autowired
    private ICmsWebService webService;

    @Autowired
    private SysConfigServiceImpl sysConfigService;

    /**
     * 查询主题列表
     */
    @PreAuthorize("@ss.hasPermi('cms:theme:list')")
    @GetMapping("/list")
    public TableDataInfo list(String webName) {
        startPage();
        List<CmsTheme> list = cmsThemeService.selectCmsThemeList(webName);
        return getDataTable(list);
    }

    /**
     * 
     * 获取主题名列表
     * 
     * @return
     */
    @PreAuthorize("@ss.hasPermi('cms:theme:list')")
    @GetMapping("/listThemeNames/{webName}")
    public AjaxResult listThemeNames(@PathVariable("webName") String webName) {
        List<String> themeNames = cmsThemeService.selectCmsThemeList(webName).stream()
                .map(CmsTheme::getThemeName).collect(Collectors.toList());
        return success(themeNames);
    }

    /**
     * 修改保存参数配置 通过key批量保存 默认设置为字符串类型
     */

    @Log(title = "主题管理", businessType = BusinessType.UPDATE)
    @PostMapping("/updateConfig/{configGroup}")
    @PreAuthorize("@ss.hasPermi('server:theme:config')")
    public AjaxResult updateConfig(@RequestBody Map<String, Object> mp,
            @PathVariable("configGroup") String configGroup) {
        mp.put("configGroup", configGroup);
        int num = sysConfigService.updatesByMap(mp, getUsername());

        return toAjax(num);
    }

    /**
     * 上传主题
     * 
     * @param file
     * @param webName
     * @param cover
     * @param coverConfig
     * @param request
     * @return
     * @throws Throwable
     */
    @PostMapping("/uploadTheme")
    @PreAuthorize("@ss.hasPermi('cms:theme:install')")
    @Log(title = "主题管理", businessType = BusinessType.INSERT)
    public AjaxResult themeUpload(@RequestParam("themeFile") MultipartFile file, String webName, boolean cover,
            boolean coverConfig,
            HttpServletRequest request) throws Throwable {
        CmsWeb cmsWeb = webService.selectCmsWebByWebName(webName);
        if (cmsWeb == null) {
            return error("站点不存在!");
        }
        if (file.isEmpty() || !"zip|gz|rar".contains(FilenameUtils.getExtension(file.getOriginalFilename()))) {
            return error("文件不存在或者不支持压缩类型,请上传.zip|.gz|.rar压缩包");
        } else {
            Map<String, String> header = new HashMap<>(1);
            Map<String, String> params = new HashMap<>();
            params.put("cover", Boolean.toString(cover));
            params.put("fileType", "zip/gz/rar");
            header.put("Accept", "application/json");
            header.put("Accept-Charset", "UTF-8");
            String s = this.uploadFile(cmsWeb.getWebUrl() + "/web/theme/uploadTheme", file,
                    "themeFile",
                    header,
                    params);
            AjaxResult aj = JSONObject.parseObject(s, AjaxResult.class);
            if (aj.get(AjaxResult.CODE_TAG).equals(HttpStatus.SUCCESS)) {
                syncThemeInfo(webName, FilenameUtils.getBaseName(file.getOriginalFilename()), coverConfig,
                        cmsWeb.getWebUrl());
            }
            return aj;
        }

    }

    @DeleteMapping("/{webName}/{themeName}")
    @PreAuthorize("@ss.hasPermi('cms:theme:remove')")
    @Log(title = "主题管理", businessType = BusinessType.DELETE)
    public AjaxResult removeTheme(@PathVariable("webName") String webName,
            @PathVariable("themeName") String themeName) {
        CmsWeb cmsWeb = webService.selectCmsWebByWebName(webName);
        if (deleteThemeFile(cmsWeb.getWebUrl() + "/web/theme/deleteTheme",
                themeName).get(AjaxResult.CODE_TAG)
                .equals(HttpStatus.SUCCESS)) {
            // 删除配置参数
            sysConfigService.deleteConfigByGroup(webName + "_" + themeName);
            CmsTheme cmsTheme = new CmsTheme();
            cmsTheme.setWebName(webName);
            cmsTheme.setThemeName(themeName);
            // 删除主题和主题关联的文章
            cmsThemeService.deleteCmsThemeByTn(cmsTheme);
            return success();
        }
        return error();
    }

    @GetMapping("/getThemeConfigForm/{webName}/{themeName}")
    @PreAuthorize("@ss.hasPermi('cms:theme:remove')")
    @Log(title = "主题管理", businessType = BusinessType.UPDATE)
    public AjaxResult getThemeConfigForm(@PathVariable("webName") String webName,
            @PathVariable("themeName") String themeName)
            throws ClientProtocolException, IOException {
        CmsWeb cmsWeb = webService.selectCmsWebByWebName(webName);
        return getConfig(cmsWeb.getWebUrl() + "/web/theme/getThemeConfigForm/" + themeName);
    }

    /**
     * 使用httpclint 发送文件
     *
     * @param file 上传的文件
     * @return 响应结果
     * @author: qingfeng
     * @date: 2020/11/23
     */
    public String uploadFile(String url, MultipartFile file, String fileParamName,
            Map<String, String> headerParams, Map<String, String> otherParams) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String result = "";
        try {
            String fileName = file.getOriginalFilename();
            HttpPost httpPost = new HttpPost(url);
            // 添加header
            for (Map.Entry<String, String> e : headerParams.entrySet()) {
                httpPost.addHeader(e.getKey(), e.getValue());
            }
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setCharset(Charset.forName("utf-8"));
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);// 加上此行代码解决返回中文乱码问题
            builder.addBinaryBody(fileParamName, file.getInputStream(), ContentType.MULTIPART_FORM_DATA, fileName);// 文件流
            for (Map.Entry<String, String> e : otherParams.entrySet()) {
                builder.addTextBody(e.getKey(), e.getValue());// 类似浏览器表单提交，对应input的name和value
            }
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);
            HttpResponse response = httpClient.execute(httpPost);// 执行提交
            HttpEntity responseEntity = response.getEntity();
            if (responseEntity != null) {
                // 将响应内容转换为字符串
                result = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public void syncThemeInfo(String webName, String themeName, boolean coverConfig, String url)
            throws ClientProtocolException, IOException {
        CmsTheme searchTheme = new CmsTheme();
        searchTheme.setWebName(webName);
        searchTheme.setThemeName(themeName);
        // 获取配置Json
        JSONObject con = JSONObject
                .parseObject(
                        getConfig(url + "/web/theme/getThemeSetting/" + themeName).get(AjaxResult.DATA_TAG).toString())
                .getJSONObject("data");
        CmsTheme theme = JSONObject.parseObject(
                JSON.toJSONString(
                        con.get(OlyThemeConfigProperties.THEME_DATA_PREFIX.defaultValue())),
                CmsTheme.class);
        theme.setWebName(webName);
        theme.setCreateBy(getUsername());
        theme.setThemeEnabled(null);
        if (cmsThemeService.selectCmsThemeByTn(searchTheme) != null && coverConfig) {
            cmsThemeService.updateCmsTheme(theme);
            addThemeConfig(JSON.parseArray(
                    JSON.toJSONString(
                            con.get(OlyThemeConfigProperties.THEME_CONFIG_PREFIX.defaultValue())),
                    SysConfig.class), themeName, webName);
        } else {
            theme.setThemeEnabled(0);
            cmsThemeService.insertCmsTheme(theme);
            addThemeConfig(JSON.parseArray(
                    JSON.toJSONString(
                            con.get(OlyThemeConfigProperties.THEME_CONFIG_PREFIX.defaultValue())),
                    SysConfig.class), themeName, webName);
        }

    }

    /**
     * 读取配置
     * 
     * @param listConfigs
     * @param themeName
     */
    private void addThemeConfig(List<SysConfig> listConfigs, String themeName, String webName) {
        if (StringUtils.isNotEmpty(listConfigs)) {
            for (SysConfig sysConfig : listConfigs) {
                if (themeName.equals(sysConfig.getConfigGroup())
                        && sysConfig.getConfigKey().startsWith(OlyWebConfigProperties.THEME_CONFIG_PREFIX.getValue())) {
                    sysConfig.setConfigType("N");
                    sysConfig.setConfigGroup(webName + "_" + sysConfig.getConfigGroup());
                    if (sysConfigService.selectConfigByGk(sysConfig.getConfigGroup(),
                            sysConfig.getConfigKey()) != null) {
                        sysConfig.setUpdateBy("");
                        sysConfigService.updateConfigByGk(sysConfig);
                    } else {
                        sysConfig.setCreateBy("");
                        sysConfigService.insertConfig(sysConfig);
                    }
                }
            }
        }
    }

    private AjaxResult deleteThemeFile(String url, String themeName) {
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        formparams.add(new BasicNameValuePair("themeName", themeName));
        return post(url, formparams);
    };

    /**
     * 发送 post请求访问本地应用并根据传递参数不同返回不同结果
     */
    private AjaxResult post(String url, List<NameValuePair> formparams) {
        // 创建默认的httpClient实例.
        CloseableHttpClient httpclient = HttpClients.createDefault();
        // 创建httppost
        HttpPost httppost = new HttpPost(url);
        // 创建参数队列
        UrlEncodedFormEntity uefEntity;
        try {
            uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
            httppost.setEntity(uefEntity);
            CloseableHttpResponse response = httpclient.execute(httppost);
            try {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    return JSONObject.parseObject(EntityUtils.toString(entity, "UTF-8"), AjaxResult.class);
                }
            } finally {
                response.close();
            }
        } catch (ClientProtocolException e) {
            System.out.println(e);
        } catch (UnsupportedEncodingException e1) {
            System.out.println(e1);
        } catch (IOException e) {
            System.out.println(e);
        } finally {
            // 关闭连接,释放资源
            try {
                httpclient.close();
            } catch (IOException e) {
                System.out.println(e);
            }
        }
        return error();
    }

    private AjaxResult getConfig(String url) throws ClientProtocolException, IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault();

        HttpGet httpGet = new HttpGet(url);

        CloseableHttpResponse response = httpClient.execute(httpGet);

        try {

            return JSONObject.parseObject(EntityUtils.toString(response.getEntity(), "UTF-8"), AjaxResult.class);

        } finally {

            response.close();

        }

    }

}
